package cn.itcast.n8;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;

import static cn.itcast.n2.util.Sleeper.sleep;

@Slf4j(topic = "c.TestCountDownLatch")
public class TestCountDownLatch {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        RestTemplate restTemplate = new RestTemplate();
        log.debug("begin");
//        Map<String, Object> response = restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
//        log.debug("end order：{}",response);
//        Map<String, Object> response1 = restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
//        Map<String, Object> response2 = restTemplate.getForObject("http://localhost:8080/product/{2}", Map.class, 2);
//        log.debug("end product：{},{}",response1,response2);
//
//        Map<String, Object> response3 = restTemplate.getForObject("http://localhost:8080/logistics/{1}", Map.class, 1);
//        log.debug("end logistics：{}",response3);

//        final CountDownLatch latch = new CountDownLatch(4);
        final ExecutorService pool = Executors.newCachedThreadPool();
        final Future<Map<String, Object>> f1 = pool.submit(() -> {
            Map<String, Object> response = restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
            return response;
        });

        final Future<Map<String, Object>> f2 = pool.submit(()->{
            Map<String, Object> response1 = restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
            return response1;
        });

        final Future<Map<String, Object>> f3 = pool.submit(()->{
            Map<String, Object> response2 = restTemplate.getForObject("http://localhost:8080/product/{2}", Map.class, 2);
            return response2;
        });

        final Future<Map<String, Object>> f4 = pool.submit(()->{
            Map<String, Object> response3 = restTemplate.getForObject("http://localhost:8080/logistics/{1}", Map.class, 1);
            return response3;
        });
        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());

//        latch.await();
        log.debug("查询完成...");
        pool.shutdown();
    }

    private static void countDownTest(RestTemplate restTemplate) throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(4);
        final ExecutorService pool = Executors.newCachedThreadPool();
        pool.submit(()->{
            Map<String, Object> response = restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
            log.debug("end order：{}",response);
            latch.countDown();
        });

        pool.submit(()->{
            Map<String, Object> response1 = restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
            log.debug("end product：{}",response1);
            latch.countDown();
        });

        pool.submit(()->{
            Map<String, Object> response2 = restTemplate.getForObject("http://localhost:8080/product/{2}", Map.class, 2);
            log.debug("end product：{}",response2);
            latch.countDown();
        });

        pool.submit(()->{
            Map<String, Object> response3 = restTemplate.getForObject("http://localhost:8080/logistics/{1}", Map.class, 1);
            log.debug("end logistics：{}",response3);
            latch.countDown();
        });

        latch.await();
        log.debug("查询完成...");
        pool.shutdown();
    }

    private static void test4() throws InterruptedException, ExecutionException {
        RestTemplate restTemplate = new RestTemplate();
        log.debug("begin");
        ExecutorService service = Executors.newCachedThreadPool();
        CountDownLatch latch = new CountDownLatch(4);
        Future<Map<String,Object>> f1 = service.submit(() -> {
            Map<String, Object> response = restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
            return response;
        });
        Future<Map<String, Object>> f2 = service.submit(() -> {
            Map<String, Object> response1 = restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
            return response1;
        });
        Future<Map<String, Object>> f3 = service.submit(() -> {
            Map<String, Object> response1 = restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 2);
            return response1;
        });
        Future<Map<String, Object>> f4 = service.submit(() -> {
            Map<String, Object> response3 = restTemplate.getForObject("http://localhost:8080/logistics/{1}", Map.class, 1);
            return response3;
        });

        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());
        log.debug("执行完毕");
        service.shutdown();
    }

    private static void test3() throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(10);
        final ExecutorService pool = Executors.newFixedThreadPool(10);
        final Random r = new Random();
        String[] all =new String[10];

        for (int i = 0; i < 10; i++) {
            int finalI = i;
            pool.submit(()->{
                for (int j = 0; j < 101; j++) {
                    try {
                        Thread.sleep(r.nextInt(100));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    all[finalI] = j+"%";
                    System.out.print("\r"+Arrays.toString(all));
                }
                latch.countDown();
            });
        }


        latch.await();
        System.out.println("\n游戏开始");

        pool.shutdown();
    }

    private static void test2() {
        final CountDownLatch latch = new CountDownLatch(3);
        final ExecutorService pool = Executors.newFixedThreadPool(2);

        pool.submit(() -> {
            log.debug("begin...");
            sleep(1);
            latch.countDown();
            log.debug("end...{}",latch.getCount());
        });

        pool.submit(() -> {
            log.debug("begin...");
            sleep(1.5);
            latch.countDown();
            log.debug("end...{}",latch.getCount());
        });

        pool.submit(() -> {
            log.debug("begin...");
            sleep(2);
            latch.countDown();
            log.debug("end...{}",latch.getCount());
        });

        pool.submit(() -> {
            log.debug("wating...");
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("wating end...");
        });
    }

    private static void test1() throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(3);

        new Thread(() -> {
            log.debug("begin...");
            sleep(1);
            latch.countDown();
            log.debug("end...{}",latch.getCount());
        },"t1").start();

        new Thread(() -> {
            log.debug("begin...");
            sleep(2);
            latch.countDown();
            log.debug("end...{}",latch.getCount());
        },"t2").start();

        new Thread(() -> {
            log.debug("begin...");
            sleep(1.5);
            latch.countDown();
            log.debug("end...{}",latch.getCount());
        },"t3").start();


        log.debug("wating...");
        latch.await();
        log.debug("wating end...");
    }
}
